/*
 * Level.cpp
 *
 *  Created on: 15 févr. 2011
 *      Author: seeme
 */

#include "Level.h"
#include <iterator>
#include "../../../Tools/Misc/Singleton.h"
#include "../../../Tools/Geometry/Point.h"
#include "../../../Tools/Geometry/Triangle.h"
#include "../../../Tools/Geometry/Matrix4.h"
#include "../../../Scene/Lights/AmbiantLight.h"
#include "../../../Scene/Lights/OmniLight.h"

Level::~Level() {
	//Log::d("Level") << "Destroying level file";
}

size_t Level::getSize(){
	//To be fixed, ugly hack for now...
	return m_size;
}

bool Level::create(){
	Log::d("Level") << "Creating level data";
	openFile();

	std::string name;
	Vect4<float> translation, rotation, scale, vpos;

	Log::d("Level") << "Parsing...";
	TiXmlHandle hdl(&m_data);
	TiXmlElement *object = hdl.FirstChildElement().FirstChildElement("entity").Element();
	TiXmlElement *next;

	ResCache * s = Singleton<ResCache>::get();

	Mesh* m;

	unsigned int nbLight = 0;

	while(object){
		name = object->Attribute("name");


		//On lit la position
		next = object->FirstChildElement("translation");
		translation.x = atof(next->Attribute("x"));
		translation.y = atof(next->Attribute("y"));
		translation.z = atof(next->Attribute("z"));

		//Rotation
		next = object->FirstChildElement("rotation");
		rotation.x = atof(next->Attribute("x"));
		rotation.y = atof(next->Attribute("y"));
		rotation.z = atof(next->Attribute("z"));

		//Taille
		next = object->FirstChildElement("scale");
		scale.x = atof(next->Attribute("x"));
		scale.y = atof(next->Attribute("y"));
		scale.z = atof(next->Attribute("z"));
		if((scale.x == scale.y) && (scale.y == scale.z) && (scale.z == 0)){
			scale.x = 1.;
			scale.y = 1.;
			scale.z = 1.;
		}

		m = (Mesh*)s->getResource(name);

		addEntity(new StaticDrawableEntity(translation, (180./M_PI)*rotation, scale, m));

		object = object->NextSiblingElement("entity");
	}

	//On lit les lampes...

	std::string type, Lname;
	Vect4<float> color, Lposition;

	object = hdl.FirstChildElement().FirstChildElement("light").Element();
	while(object){
		//Type de lampe
		type = object->Attribute("type");

		//Couleur
		next = object->FirstChildElement("color");
		color.x = atof(next->Attribute("r"));
		color.y = atof(next->Attribute("g"));
		color.z = atof(next->Attribute("b"));
		color.w = atof(next->Attribute("a"));

		//Si c'est une omni
		//TODO
		//On aurait besoin d'une factory ici..
		if(strcmp(type.c_str(), "omni") == 0){
			next = object->FirstChildElement("position");
			Lposition.x = atof(next->Attribute("x"));
			Lposition.y = atof(next->Attribute("y"));
			Lposition.z = atof(next->Attribute("z"));
			m_omnis.push_back(new OmniLight(color, Lposition, nbLight++));
		}else{
			m_ambiant = new AmbiantLight(color);
		}

		object = object->NextSiblingElement("light");
	}

	m_size = 1;
	Log::i("Level") << "Done";
	return true;
}

void Level::addEntity(StaticDrawableEntity* entity){
	//Simply add to the root node for now
	if(m_sceneGraph.getValue()){
		m_sceneGraph.addChild(new sNode<StaticDrawableEntity*>(entity));
	}else{
		m_sceneGraph.setValue(entity);
	}
}

void Level::destroy(){
	m_size = 0;

	//delete everything
	delGraph(m_sceneGraph);

	for(unsigned int i = 0; i < m_omnis.size(); ++i)
		delete m_omnis.at(i);
	m_omnis.clear();

	if(m_ambiant != NULL)
		delete m_ambiant;
}

void Level::delGraph(sNode<StaticDrawableEntity*>& node){
	if(node.getValue() != NULL){
		delete node.getValue();
	}

	std::list<sNode<StaticDrawableEntity*>* > children = node.getChildren();

	if(children.size() > 0){
		std::list<sNode<StaticDrawableEntity*>* >::iterator iter = children.begin();
		for( ; iter != children.end(); iter++)
			delGraph(**iter);
	}
}
